/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-08-23 17:30:57
 * @LastEditTime: 2021-08-25 15:58:02
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include "ft_debug.h"
#include "fsleep.h"
#include "parameters.h"
#include "kernel.h"
#include "ft_assert.h"
#include "gmac.h"
#include "gmac_dma.h"
#include "gmac_hw.h"

#define GMAC_RX_DESCNUM     16//1024U
#define GMAC_TX_DESCNUM     16//1024U

static GmacCtrl gmac;
/* align buf and descriptor by 128 */
static u8 txBuf[GMAC_TX_DESCNUM * GMAC_MAX_PACKET_SIZE] __aligned(GMAC_DMA_MIN_ALIGN);
static u8 rxBuf[GMAC_RX_DESCNUM * GMAC_MAX_PACKET_SIZE] __aligned(GMAC_DMA_MIN_ALIGN);
static GmacDmaDesc txDesc[GMAC_TX_DESCNUM] __aligned(GMAC_DMA_MIN_ALIGN);
static GmacDmaDesc rxDesc[GMAC_RX_DESCNUM] __aligned(GMAC_DMA_MIN_ALIGN);
static volatile boolean inputReached = FALSE;

void GmacRecvCB(void *para)
{
    FT_ASSERTVOID(para);
    GmacCtrl *pCtrl = (GmacCtrl *)para;

    inputReached = TRUE;
    printf("rx intrrupt\r\n");
}

void GmacTransCB(void *para)
{
    FT_ASSERTVOID(para);
    GmacCtrl *pCtrl = (GmacCtrl *)para;

    GmacDmaResumeTran(pCtrl);
    printf("tx intrrupt\r\n");
}

void EthLowLevelInput(GmacCtrl *pCtrl)
{
    u32 ret = GMAC_SUCCESS;
    u32 bufIdx, length, bytesLeftToCp, bufOffset;
    u8 *pRxBuf;
    volatile GmacDmaDesc *pCurRxDesc;

    /* read rx buffer */
    ret = GmacDmaRxFrame(pCtrl);
    if (GMAC_SUCCESS != ret)
    {
        printf("+\r\n");
        return;
    }
    
    /* handle received frame */
    printf("frame received\r\n");
    bufIdx = pCtrl->rxRing.descBufIdx;
    length = (pCtrl->rxDesc[bufIdx].status & GMAC_DMA_RDES0_FRAME_LEN_MASK) >> GMAC_DMA_RDES0_FRAME_LEN_SHIFT;
    pRxBuf = (u8 *)pCtrl->rxDesc[bufIdx].buf1Addr;
    FtDumpHexWord((u32 *)pRxBuf, length);

    /* give tx buf to DMA */
    for (bufIdx = pCtrl->rxRing.descBufIdx; 
         bufIdx != pCtrl->rxRing.descIdx;
         GMAC_DMA_INC_DESC(bufIdx, pCtrl->rxRing.descMaxNum))
    {
        pCurRxDesc = &pCtrl->rxDesc[bufIdx];
        pCurRxDesc->status |= GMAC_DMA_RDES0_OWN;
    }

    return;
}

void EthInputLoop(GmacCtrl *pCtrl)
{
    u32 cnt = 0;
    u32 regVal;

    while (TRUE)
    {
        if (TRUE == inputReached)
        {
            //GmacDmaProbe(pCtrl);
            EthLowLevelInput(pCtrl);
            inputReached = FALSE;
            GMAC_W1C_BIT(pCtrl, GMAC_DMA_STATUS_OFFSET, GMAC_DMA_STATUS_RI);
            GmacDmaResumeRecv(pCtrl);
            //GmacDmaProbe(pCtrl);
            printf("resume rx \r\n");
        }

        if (1000 < ++cnt)
        {
            printf(".\r\n");
            cnt = 0;
        }
        fsleep_microsec(100);
    }
}

void GmacInitTest()
{
    u32 ret = GMAC_SUCCESS;

    memset(&gmac, 0U, sizeof(gmac));
    ret |= GmacCfgInitialize(&gmac, GmacLookupConfig(GMAC_INSTANCE_0));

    if (GMAC_SUCCESS != ret)
    {
        printf("init cfg failed\r\n");
        return;
    }

    ret = GmacHwInitialize(&gmac);
    if (GMAC_SUCCESS != ret)
    {
        printf("init hardware failed\r\n");
        return;
    }

    ret |= GmacDmaInitRxDescRing(&gmac, &rxDesc[0], &rxBuf[0], GMAC_MAX_PACKET_SIZE, GMAC_RX_DESCNUM);
    ret |= GmacDmaInitTxDescRing(&gmac, &txDesc[0], &txBuf[0], GMAC_MAX_PACKET_SIZE, GMAC_TX_DESCNUM);
    if (GMAC_SUCCESS != ret)
    {
        printf("init dma ring data failed\r\n");
        return;
    }

    ret = GmacIntrInit(&gmac);
    if (GMAC_SUCCESS != ret)
    {
        printf("init gmac intrrupt failed\r\n");
        return;
    }

    GmacRegisterEvtHandler(&gmac, GMAC_RX_COMPLETE_EVT, GmacRecvCB);
    GmacRegisterEvtHandler(&gmac, GMAC_TX_COMPLETE_EVT, GmacTransCB);

    GmacSetIntrMask(&gmac, GMAC_DMA_INTR, GENMASK(16, 0), TRUE);
    printf("gmac init success\r\n");

    GmacDmaStart(&gmac);
    EthInputLoop(&gmac);
    return;
}